package cn.ac.siom.query.common.realm;

import cn.ac.siom.query.common.exception.UserNotPermitException;
import cn.ac.siom.query.service.UserService;
import cn.ac.siom.query.vo.Permission;
import cn.ac.siom.query.vo.Role;
import cn.ac.siom.query.vo.Sys_user;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

;

public class CardRealm extends AuthorizingRealm {
    public static final Logger LOGGER = LoggerFactory.getLogger(CardRealm.class);

    @Resource
    UserService getUserService;

    // 用户对应的角色信息与权限信息都保存在数据库中，通过UserService获取数据


    /**
     * 提供用户信息返回权限信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) throws AccountException {
        String username = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 根据用户名查询当前用户拥有的角色
        Sys_user user = null;
        //String roles=null;
        try {
            user = getUserService.finderoles(username);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        Set<String> roleNames = new HashSet<String>();
        if(user.getRoleList()!= null) {
            for (Role role : user.getRoleList()) {
                System.out.println(role.getRname());
                LOGGER.debug("从数据库获取用户role"+role.getRname());

                roleNames.add(role.getRname());
                LOGGER.debug("用户role添加到认证信息"+roleNames);
                System.out.println(roleNames);
            }
        }else{

        }
        //roleNames.add(roles);

        // 将角色名称提供给info
        if(roleNames.size() != 0) {
            authorizationInfo.setRoles(roleNames);
        }
        // 根据用户名查询当前用户权限
        Sys_user user2 = null;
        try {
            user2 = getUserService.findPermissions(username);
            LOGGER.debug("从数据库获取用户权限:"+user2);
            System.out.println(user2);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        Set<String> permissionNames = new HashSet<String>();
        if(user2.getRoleList() != null) {
            for (Role role : user2.getRoleList()) {
                for (Permission permission : role.getPermissionList()) {
                    permissionNames.add(permission.getPname());
                    LOGGER.debug("用户角色对应的权限名:"+permission.getPname());
                    System.out.println(permission.getPname());
                    LOGGER.debug("权限名:"+permissionNames);
                    System.out.println(permissionNames);
                }
            }
        }else{
            throw new UserNotPermitException();
        }
        // 将权限名称提供给info
        if(permissionNames.size() != 0) {
            authorizationInfo.setStringPermissions(permissionNames);
            System.out.println();
        }
        return authorizationInfo;
    }




    /**
     * 设置session
     *
     * @param key   session的key
     * @param value session的value
     */
    private void setSession(Object key, Object value) {
        Subject currentUser = SecurityUtils.getSubject();
        if (null != currentUser) {
            Session session = currentUser.getSession();
            if (null != session) {
                session.setAttribute(key, value);

            }
        }
    }



    /**
     * 提供账户信息返回认证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        Sys_user user = new Sys_user();

        // 1. 把AuthenticationToken转换为UsernamePasswordToken
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        // 2. 从UsernamePasswordToken中获取email
        String email = upToken.getUsername();
        user.setU_email(email);
        //String email=user.getU_email();
        // 3. 若用户不存在，抛出UnknownAccountException异常
        try {
            user = getUserService.getUserInfo(user);

        } catch (SQLException e) {
            e.printStackTrace();
        }
        if (user == null )
            throw new UnknownAccountException("用户不存在！");

        // 4.
        // 根据用户的情况，来构建AuthenticationInfo对象并返回，通常使用的实现类为SimpleAuthenticationInfo
        // 以下信息从数据库中获取
        // （1）principal：认证的实体信息，可以是email，也可以是数据表对应的用户的实体类对象
        Object principal = email;
        // （2）credentials：密码
        Object credentials = user.getU_pwd();
        // （3）realmName：当前realm对象的name，调用父类的getName()方法即可
        String realmName = getName();

        // （4）盐值：取用户信息中唯一的字段来生成盐值，避免由于两个用户原始密码相同，加密后的密码也相同
        ByteSource credentialsSalt = ByteSource.Util.bytes(user.getU_salt());
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt,
                realmName);

        return info;
    }

}
